﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using ZTool.Domain;
using ZTool.Domain.DO;
using ZTool.Model;

namespace ZTool.ViewModel
{
    class MainViewModel : ViewModelBase
    {
        #region Properties
        private string appTitle;
        public string AppTitle { get => appTitle; set => SetProperty(ref appTitle, value); }
        private string _inputText, _outputText;
        public string InputText { get => _inputText; set => SetProperty(ref _inputText, value); }
        public string OutputText { get => _outputText; set => SetProperty(ref _outputText, value); }
        private ObservableCollection<ButtonViewModel> _buttons;
        public ObservableCollection<ButtonViewModel> Buttons { get => _buttons; set => SetProperty(ref _buttons, value); }

        private string _InputWrap, _OutputWrap;
        public string InputWrap { get => _InputWrap; set => SetProperty(ref _InputWrap, value); }
        public string OutputWrap { get => _OutputWrap; set => SetProperty(ref _OutputWrap, value); }
        private Window window;

        private RegistryCenterService registryCenterService;
        #endregion
        #region ctor
        public MainViewModel(Window window)
        {
            this.window = window;

            init();
        }


        #endregion
        #region methods
        private void init()
        {
            AppTitle = $"{Constants.APP_NAME} v{Constants.VERSION}";

            initButtons();

            InputWrap = AppHelper.Inst.GetInputWrapType();
            OutputWrap = AppHelper.Inst.GetOutputWrapType();

            registryCenterService = new RegistryCenterService();
            registryCenterService.HandleRequestsCompleted += RegistryCenterService_HandleRequestsCompleted;
        }

        private void RegistryCenterService_HandleRequestsCompleted(object sender, EventArgs e)
        {
            var arg = e as RegistryEventArg;

            Log.Debug($"register new service {arg.Name} {arg.Title}");

            update();
        }

        private void update()
        {
            Buttons = new ObservableCollection<ButtonViewModel>();

            var servers = DomainFactory.Instance.GetServers();

            try
            {
                ThreadPool.QueueUserWorkItem(delegate
                {
                    System.Threading.SynchronizationContext.SetSynchronizationContext(new
                      System.Windows.Threading.DispatcherSynchronizationContext(System.Windows.Application.Current.Dispatcher));
                    System.Threading.SynchronizationContext.Current.Post(p1 =>
                    {
                        foreach (var srv in servers)
                        {
                            var bvm = convert2ButtonViewModel(srv.Value);
                            Buttons.Add(bvm);
                        }
                    }, null);
                });
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        private ButtonViewModel convert2ButtonViewModel(Server server)
        {
            ButtonViewModel buttonViewModel = new ButtonViewModel();

            buttonViewModel.Text = server.GetTitle();
            buttonViewModel.Name = server.GetName();
            buttonViewModel.ButtonCommand = WorkCommand;

            return buttonViewModel;
        }

        private void initButtons()
        {
            Buttons = new ObservableCollection<ButtonViewModel>();

            var btn = new ButtonViewModel();
            btn.Text = "test";
            btn.Name = "test";
            btn.ButtonCommand = EmptyCommand;

            Buttons.Add(btn);
        }
        private void closeClicked(object obj)
        {
            throw new NotImplementedException();
        }
        private async void workClicked(object obj)
        {
            if (string.IsNullOrEmpty(InputText) || string.IsNullOrEmpty(InputText.Trim()))
            {
                MessageBox.Show("error input text");
                return;
            }

            var bvm = obj as ButtonViewModel;
            Log.Debug($"handle {bvm.Text} {bvm.Name}");

            var response = await registryCenterService.Send(bvm.Name, Base64Util.Encode(InputText));

            if (null != response)
            {
                Trace.WriteLine($"=> {response.Code}");

                var outputToken = (response.Data as JObject)["output"];
                if (null != outputToken)
                {
                    string output = outputToken.Value<string>();
                    OutputText = Base64Util.Decode(output);
                }
            }
        }
        private void emptyClicked(object obj)
        {
            MessageBox.Show("empty clicked");
        }
        #endregion
        #region Commands
        private RelayCommand _closeCommand, _workCommand, _emptyCommand;
        public RelayCommand CloseCommand => _closeCommand ?? (_closeCommand = new RelayCommand(closeClicked));
        public RelayCommand WorkCommand => _workCommand ?? (_workCommand = new RelayCommand(workClicked));
        public RelayCommand EmptyCommand => _emptyCommand ?? (_emptyCommand = new RelayCommand(emptyClicked));


        #endregion
    }
}
